home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue40 / Diagram / MainForm.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-10-27  |  11.0 KB  |  383 lines

  1. unit MainForm;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ExtCtrls, JimShape, ComCtrls, Psock, NMHttp, ImgList;
  8.  
  9. type
  10.   TMainDlg = class(TForm)
  11.     ScrollBox1: TScrollBox;
  12.     Panel1: TPanel;
  13.     ImageList1: TImageList;
  14.     ParseBtn: TButton;
  15.     OpenDialog1: TOpenDialog;
  16.     UrlEdit: TEdit;
  17.     Label1: TLabel;
  18.     Panel2: TPanel;
  19.     ProgressBar: TProgressBar;
  20.     StatusLabel: TLabel;
  21.     CancelBtn: TButton;
  22.     Label2: TLabel;
  23.     PageNameLabel: TLabel;
  24.     NMHTTP1: TNMHTTP;
  25.     procedure ParseBtnClick(Sender: TObject);
  26.     procedure FormCreate(Sender: TObject);
  27.     procedure FormDestroy(Sender: TObject);
  28.     procedure CancelBtnClick(Sender: TObject);
  29.   private
  30.     FCurrentUrl    : string;
  31.     FParentUrlList : TStringList;
  32.     FNextChildY    : Integer;
  33.     FCurrentShape  : TjimBitmapShape;
  34.  
  35.     procedure GetHttpDocument(const Url : string);
  36.     function  CreateBitmapShape(Url : string;
  37.                                 ALeft,ATop,AImageIndex : Integer) : TjimBitmapShape;
  38.     procedure ConnectShapes(StartShape,EndShape : TjimCustomShape);
  39.     procedure ClearAll(ExceptShape : TjimBitmapShape);
  40.     procedure ParseDoc(const Doc : string);
  41.     function  GetLastParentUrl : string;
  42.     procedure RemoveLastParentUrl;
  43.     procedure AddParentUrl(const NewUrl : string);
  44.  
  45.     // Event handlers that will be assigned to diagram components
  46.     procedure ParentDblClick(Sender : TObject);
  47.     procedure CurrentDblClick(Sender : TObject);
  48.     procedure ChildDblClick(Sender : TObject);
  49.   public
  50.   end;
  51.  
  52. var
  53.   MainDlg: TMainDlg;
  54.  
  55. implementation
  56.  
  57. {$R *.DFM}
  58.  
  59. uses
  60.   JimParse;
  61.  
  62. const
  63.   ParentX  = 10;
  64.   CurrentX = 100;
  65.   ChildX   = 300;
  66.   ChildTop = 5;
  67.   ChildDY  = 70;
  68.  
  69.  
  70. function CheckUrlForSpaces(const Url : string) : string;
  71.   var
  72.     i : Integer;
  73. begin {CheckUrlForSpaces}
  74.   // Replace all occurences of '%20' with a space
  75.   Result := Url;
  76.   i      := Pos('%20',Result);
  77.  
  78.   while i > 0 do begin
  79.     Delete(Result,i,3);
  80.     Insert(' ',Result,i);
  81.     i := Pos('%20',Result);
  82.   end;
  83. end;  {CheckUrlForSpaces}
  84.  
  85.  
  86. procedure TMainDlg.GetHttpDocument(const Url : string);
  87. begin {GetHttpDocument}
  88.   // Request the HTML document
  89.   NMHTTP1.Get(Url);
  90.  
  91.   // Got whole HTML document, so parse it and display the new map
  92.   try
  93.     ParseDoc(NMHTTP1.Body);
  94.   except
  95.     on E : Exception do begin
  96.       ShowMessage(E.Message);
  97.       // Try to recover from parsing errors by stepping back through parent list
  98.       ParentDblClick(Self);
  99.     end;
  100.   end
  101. end;  {GetHttpDocument}
  102.  
  103.  
  104. function TMainDlg.CreateBitmapShape(Url : string;
  105.                                     ALeft,ATop,AImageIndex : Integer) : TjimBitmapShape;
  106. begin {CreateBitmapShape}
  107.   Result := TjimBitmapShape.Create(Self);
  108.  
  109.   with Result do begin
  110.     Top            := ATop;
  111.     Left           := ALeft;
  112.     Images         := ImageList1;
  113.     ImageIndex     := AImageIndex;
  114.     Hint           := Url;
  115.     ShowHint       := True;
  116.     Parent         := ScrollBox1;
  117.     // Create a new text shape for the caption
  118.     Caption        := TjimTextShape.Create(Self);
  119.     Caption.Parent := ScrollBox1;
  120.     Caption.Text   := Url;
  121.   end;
  122. end;  {CreateBitmapShape}
  123.  
  124.  
  125. procedure TMainDlg.ConnectShapes(StartShape,EndShape : TjimCustomShape);
  126. begin {ConnectShapes}
  127.   with TjimSingleHeadArrow.Create(Self) do begin
  128.     // Set the start connection
  129.     StartConn.Side   := csRight;
  130.     StartConn.Offset := StartShape.Height div 2;
  131.     StartConn.Shape  := StartShape;
  132.     // Set the end connection
  133.     EndConn.Side     := csLeft;
  134.     EndConn.Offset   := EndShape.Height div 2;
  135.     EndConn.Shape    := EndShape;
  136.     // Ensure the size is correct
  137.     SetBoundingRect;
  138.     // Ensure the new control is visible
  139.     Parent := ScrollBox1;
  140.   end;
  141. end;  {ConnectShapes}
  142.  
  143.  
  144. procedure TMainDlg.ClearAll(ExceptShape : TjimBitmapShape);
  145.   var
  146.     i : Integer;
  147. begin {ClearAll}
  148.   // Free all the diagram components
  149.   with ScrollBox1 do begin
  150.     i := 0;
  151.  
  152.     while i < ControlCount do begin
  153.       if (Controls[i] is TjimCustomShape) and
  154.          (Controls[i] <> ExceptShape) and
  155.          (Controls[i] <> ExceptShape.Caption) then begin
  156.         // Only want to delete the diagram controls. But DO NOT want to free
  157.         // the current control because we are probably in its on click event
  158.         // handler, and freeing the control will cause all sorts of problems
  159.         // when the event handler tries to exit
  160.         Controls[i].Free;
  161.       end else begin
  162.         Inc(i);
  163.       end;
  164.     end;
  165.   end;
  166.  
  167.   // Reset the starting point for the child page components
  168.   FNextChildY := ChildTop;
  169. end;  {ClearAll}
  170.  
  171.  
  172. procedure TMainDlg.ParseDoc(const Doc : string);
  173.   var
  174.     i         : Integer;
  175.     TempStr   : string;
  176.     BaseStr   : string;
  177.     TempIndex : Integer;
  178.     IsLink    : Boolean;
  179.     ParentShape,CurrShape,ChildShape : TjimCustomShape;
  180. begin {ParseDoc}
  181.   BaseStr := '';
  182.  
  183.   with TjimHtmlParser.Create do begin
  184.     try
  185.       if FCurrentUrl = '' then begin
  186.         ClearAll(nil);
  187.         Exit;
  188.       end;
  189.  
  190.       Parse(Doc);
  191.       // Successfully parsed the document, so clear the current display
  192.       ClearAll(FCurrentShape);
  193.  
  194.       // Create the parent and current document components
  195.       if FCurrentShape = nil then begin
  196.         CurrShape := CreateBitmapShape(FCurrentUrl,CurrentX,ScrollBox1.Height div 2,0);
  197.       end else begin
  198.         CurrShape := FCurrentShape;
  199.         CurrShape.SetBounds(CurrentX,ScrollBox1.Height div 2,
  200.                             CurrShape.Width,CurrShape.Height);
  201.       end;
  202.  
  203.       CurrShape.OnDblClick := CurrentDblClick;
  204.  
  205.       if GetLastParentUrl > '' then begin
  206.         ParentShape := CreateBitmapShape(GetLastParentUrl,ParentX,ScrollBox1.Height div 2,0);
  207.         ParentShape.OnDblClick := ParentDblClick;
  208.         // Connect the parent to the current document
  209.         ConnectShapes(ParentShape,CurrShape);
  210.       end;
  211.  
  212.       StatusLabel.Caption  := 'Drawing';
  213.       ProgressBar.Position := 0;
  214.       ProgressBar.Max      := SymbolTable.Count;
  215.  
  216.       // Step through symbol table, showing what has been found
  217.       for i := 0 to SymbolTable.Count - 1 do begin
  218.         TempStr := SymbolTable.Items[i].SymbolValue;
  219.  
  220.         case SymbolTable.Items[i].SymbolType of
  221.           stTitle : begin
  222.             PageNameLabel.Caption := TempStr;
  223.           end;
  224.  
  225.           stBase  : begin
  226.             // Replace any %20 in URL with spaces. Also, this tag should appear
  227.             // before any other links in the document, so can use it to find
  228.             // other URLs.
  229.             BaseStr := CheckUrlForSpaces(TempStr);
  230.           end;
  231.  
  232.           stLink  : begin
  233.             // Replace any %20 in URL with spaces
  234.             TempStr := BaseStr + CheckUrlForSpaces(TempStr);
  235.             IsLink  := False;
  236.  
  237.             // Determine the image to use, depening on the URL type
  238.             if StrLIComp('ftp://',PChar(TempStr),6) = 0 then begin
  239.               TempIndex := 2;
  240.             end else if StrLIComp('mailto:',PChar(TempStr),7) = 0 then begin
  241.               TempIndex := 3;
  242.             end else if StrLIComp('news:',PChar(TempStr),5) = 0 then begin
  243.               TempIndex := 4;
  244.             end else if StrLIComp('file://',PChar(TempStr),7) = 0 then begin
  245.               TempIndex := 0;
  246.             end else begin
  247.               TempIndex := 0;
  248.               IsLink    := True;
  249.  
  250.               if StrLIComp('http://',PChar(TempStr),7) <> 0 then begin
  251.                 // Trying to load a document with a relative path to the
  252.                 // current one. Make the path absolute.
  253.                 if not ((FCurrentUrl[Length(FCurrentUrl)] in ['/','\']) or
  254.                         ((Length(TempStr) > 0) and (TempStr[1] in ['/','\']))) then begin
  255.                   TempStr := '/' + TempStr;
  256.                 end;
  257.  
  258.                 TempStr := FCurrentUrl + TempStr;
  259.               end;
  260.             end;
  261.  
  262.             // Create diagram component for this URL, and link to diagram
  263.             // component for current URL
  264.             ChildShape := CreateBitmapShape(TempStr,ChildX,FNextChildY,TempIndex);
  265.             Inc(FNextChildY,ChildDY);
  266.             // Connect this shape to the current document component
  267.             ConnectShapes(CurrShape,ChildShape);
  268.  
  269.             if IsLink and Assigned(ChildShape) then begin
  270.               ChildShape.OnDblClick := ChildDblClick;
  271.             end;
  272.           end;
  273.  
  274.           stImage : begin
  275.             // Replace any %20 in URL with spaces
  276.             TempStr := BaseStr + CheckUrlForSpaces(TempStr);
  277.             // Create diagram component for this URL, and link to diagram
  278.             // component for current URL
  279.             ChildShape := CreateBitmapShape(TempStr,ChildX,FNextChildY,1);
  280.             Inc(FNextChildY,ChildDY);
  281.             // Connect this shape to the current document component
  282.             ConnectShapes(CurrShape,ChildShape);
  283.           end;
  284.         end;
  285.  
  286.         ProgressBar.Position := i + 1;
  287.       end;
  288.  
  289.       Application.ProcessMessages;
  290.     finally
  291.       StatusLabel.Caption  := 'Finished';
  292.       ProgressBar.Position := 0;
  293.       Free;
  294.     end;
  295.   end;
  296. end;  {ParseDoc}
  297.  
  298.  
  299. function TMainDlg.GetLastParentUrl : string;
  300. begin {GetLastParentUrl}
  301.   Result := '';
  302.  
  303.   if FParentUrlList.Count > 0 then begin
  304.     Result := FParentUrlList[FParentUrlList.Count - 1];
  305.   end;
  306. end;  {GetLastParentUrl}
  307.  
  308.  
  309. procedure TMainDlg.RemoveLastParentUrl;
  310. begin {RemoveLastParentUrl}
  311.   if FParentUrlList.Count > 0 then begin
  312.     FParentUrlList.Delete(FParentUrlList.Count - 1);
  313.   end;
  314. end;  {RemoveLastParentUrl}
  315.  
  316.  
  317. procedure TMainDlg.AddParentUrl(const NewUrl : string);
  318. begin {AddParentUrl}
  319.   FParentUrlList.Add(NewUrl);
  320. end;  {AddParentUrl}
  321.  
  322.  
  323. procedure TMainDlg.ParentDblClick(Sender : TObject);
  324. begin {ParentDblClick}
  325.   if Sender is TjimBitmapShape then begin
  326.     FCurrentShape := TjimBitmapShape(Sender);
  327.   end;
  328.  
  329.   // Ensure that the parent becomes the current URL
  330.   FCurrentUrl := GetLastParentUrl;
  331.   RemoveLastParentUrl;
  332.   GetHttpDocument(FCurrentUrl);
  333. end;  {ParentDblClick}
  334.  
  335.  
  336. procedure TMainDlg.CurrentDblClick(Sender : TObject);
  337. begin {CurrentDblClick}
  338.   // Do nothing in this demo. Could fire up an HTML editor
  339. end;  {CurrentDblClick}
  340.  
  341.  
  342. procedure TMainDlg.ChildDblClick(Sender : TObject);
  343. begin {ChildClick}
  344.   if Sender is TjimBitmapShape then begin
  345.     // Ensure that the child becomes the current URL
  346.     FCurrentShape := TjimBitmapShape(Sender);
  347.     AddParentUrl(FCurrentUrl);
  348.     FCurrentUrl := TjimBitmapShape(Sender).Caption.Text;
  349.     GetHttpDocument(FCurrentUrl);
  350.   end;
  351. end;  {ChildDblClick}
  352.  
  353.  
  354. procedure TMainDlg.FormCreate(Sender: TObject);
  355. begin
  356.   FCurrentUrl    := '';
  357.   FParentUrlList := TStringList.Create;
  358. end;
  359.  
  360.  
  361. procedure TMainDlg.FormDestroy(Sender: TObject);
  362. begin
  363.   FParentUrlList.Free;
  364. end;
  365.  
  366.  
  367. procedure TMainDlg.ParseBtnClick(Sender: TObject);
  368. begin
  369.   FParentUrlList.Clear;
  370.   FCurrentUrl   := UrlEdit.Text;
  371.   FCurrentShape := nil;
  372.   GetHttpDocument(FCurrentUrl);
  373. end;
  374.  
  375.  
  376. procedure TMainDlg.CancelBtnClick(Sender: TObject);
  377. begin
  378.   NMHTTP1.Abort;
  379. end;
  380.  
  381.  
  382. end.
  383.